package com.dake.jdk8.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

public class SpringBeanHolder implements ApplicationContextAware, InitializingBean {

    private static ApplicationContext applicationContext;

    /**
     * 获取存储在静态变量中的{@link org.springframework.context.ApplicationContext}
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        validateApplicationContextNull();
        return applicationContext;
    }

    /**
     * 从静态变量{@code applicationContext}中获取{@code bean}，自动转型为入参对象类型{@code T}
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        validateApplicationContextNull();
        return applicationContext.getBean(clazz);
    }

    /**
     * 将{@link String}类型的对象名转化为对应的对象
     *
     * @param beanName
     * @param <T>
     * @return
     */
    public static <T> T getbean(String beanName) {
        validateApplicationContextNull();
        return (T) applicationContext.getBean(beanName);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(SpringBeanHolder.applicationContext, "Bean初始化失败");
    }

    /**
     * 实现{@link org.springframework.context.ApplicationContext}接口的回调方法，设置上下文环境，注入Context到静态变量中
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanHolder.applicationContext = applicationContext;
    }

    /**
     * 校验{@code applicationContext}的非空性
     */
    private static void validateApplicationContextNull() {
        Assert.notNull(applicationContext, "applicationContext属性未注入，请在applicationContext.xml中定义说");
    }
}
